/*
 * Copyright 2020-2030 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitee.minimalismstyle.fresh.gateway.filter

import com.fasterxml.jackson.databind.ObjectMapper
import com.gitee.minimalismstyle.fresh.common.core.const.CacheConst
import com.gitee.minimalismstyle.fresh.gateway.config.CaptchaProperties
import com.gitee.minimalismstyle.fresh.gateway.handler.CaptchaHandler
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory
import org.springframework.stereotype.Component
import reactor.core.publisher.Mono

/**
 * 验证码拦截器
 * @author maoxiaodong
 */
@Component
class CaptchaGatewayFilterFactory(val objectMapper: ObjectMapper,
                                  val captchaHandler: CaptchaHandler,
                                  val captchaProperties: CaptchaProperties) :
        AbstractGatewayFilterFactory<CaptchaGatewayFilterConfig>(CaptchaGatewayFilterConfig::class.java) {

    override fun apply(config: CaptchaGatewayFilterConfig): GatewayFilter {

        return GatewayFilter { exchange, chain ->
            val request = exchange.request
            val path = request.uri.path
            // 处理需要验证码的请求
            if (config.uri.contains(path) && captchaProperties.enabled) {
                //校验验证码
                val captchaToken = request.queryParams.getFirst(CacheConst.CAPTCHA_TOKEN_KEY)
                val captcha = request.queryParams.getFirst("captcha")
                val r = captchaHandler.checkCaptcha(captchaToken!!, captcha!!, true)
                if (!r.success) {
                    val response = exchange.response
                    response.writeWith(Mono.just(response.bufferFactory()
                            .wrap(objectMapper.writeValueAsBytes(r))))
                } else {
                    chain.filter(exchange)
                }

            } else {
                chain.filter(exchange)
            }
        }
    }
}
